package net.hyperz.showtime.fragments;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import net.hyperz.showtime.R;
import net.hyperz.showtime.ui.Utility;
import net.hyperz.showtime.utils.Data;
import net.hyperz.showtime.utils.Data.Network;
import net.hyperz.showtime.utils.Data.Provider;
import net.hyperz.showtime.utils.Data.Show;

import android.app.Dialog;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

@SuppressWarnings("unused")
public class LineupGrid extends Fragment {
	
	private String mPostCode = "V8Z7X8";
	private String mProviderZapId = "";
	private Context mCtx;
	private ProviderDataListAdapter mProviderDataAdapter = null;
	private ListView mDialogProviderListView = null;
	
	public LineupGrid() { }
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		
		if (savedInstanceState != null) {
			mProviderZapId = (savedInstanceState.getString("ProviderZapId") != null) ? savedInstanceState.getString("ProviderZapId") : "";
			mPostCode = (savedInstanceState.getString("PostCode") != null) ? savedInstanceState.getString("PostCode") : "";
		}
		
		List<Network> networks = new ArrayList<Network>();
		
		//TODO check the 'Preferences' for the users post code
		
		if (mProviderZapId.length() == 0) {
			presentProviderSelectionDialog();
		} else {
			new LoadNetworkData().execute(mPostCode, mProviderZapId);
		}
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRetainInstance(true);
		
		mCtx = this.getActivity();
	}
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putString("ProviderZapId", mProviderZapId);
		outState.putString("PostCode", mPostCode);
	}
	
	private class LoadNetworkData extends AsyncTask<String, Integer, List<Network>> {
		ProgressDialog progress = new ProgressDialog(mCtx);
		Data data = new Data(mCtx);
		
		@Override
        public void onPreExecute() {
			progress.setCanceledOnTouchOutside(false);
			progress.setCancelable(false);
			progress.setMessage("Loading Show Data ...");
			progress.show();
		}
		
		@Override
        public void onPostExecute(List<Network> networks) {
			loadNetworkDataIntoGrid(networks);
			progress.dismiss();
		}
		
		@Override
		protected List<Network> doInBackground(String... params) {
			return data.LoadNetworks(params[0], params[1]);
		}
	}
	
	private void loadNetworkDataIntoGrid(List<Network> networks) {
		
		DisplayMetrics dm = this.getResources().getDisplayMetrics();
		// columns will be about 1" in real size
		// we get the inches by dividing the pixels by the dpi e.g. 1024 / 160 = 6.4" or 6"
		// then we'll add 1 in order to account for the network column 
		int columnCount = (int) (dm.widthPixels / dm.densityDpi) + 1;
		//row count is determined by the network count
		int rowCount = networks.size();
		
		View view = this.getView();
		
		buildHeaderRow(view, columnCount);
		
		TableRow headerRow = (TableRow) view.findViewById(R.id.header_row);
		int width = headerRow.getWidth();
		
		//grab instance of header row view and set the weightSum 
		TableLayout dataTable = (TableLayout) view.findViewById(R.id.data_table);
		TableLayout.LayoutParams tblp = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
				TableLayout.LayoutParams.MATCH_PARENT, 1f);
		
		for (int currentRow=0;currentRow<rowCount;currentRow++) {
			TableRow dataRow = new TableRow(getActivity());
			dataRow.setWeightSum(columnCount);
			
			int showIndex = 0; int columnIndex = 1;
			//Log.v("LineupGrid", "Total Shows for Row " + currentRow + " is " + networks.get(currentRow).Shows.size());
			//loop through the colCount and create a column for each slot
			for (int currentColumn=0;currentColumn<=(columnCount - 1);currentColumn++) {
				if (showIndex >= networks.get(currentRow).Shows.size()) {
					//whoa! we can't have an index of more shows than we have, break out.
					break;
				}
				
				if (currentColumn == 0) {
					//the first row will always contain the network information
					Utility.CreateGridNetworkColumn(getActivity(), networks.get(currentRow), dataRow);
				} else {
					//Log.v("LineupGrid", "ColIdx = " + columnIndex + " CurCol = " + currentColumn + " for Row " + currentRow);
					
					if (columnIndex == currentColumn) {
						Show currentShow = networks.get(currentRow).Shows.get(showIndex);
						float weight = Utility.CreateGridTimeSlot(getActivity(), currentShow, dataRow);
						float cumlativeWeight = 1f;
						
						if (weight < cumlativeWeight) {
							//Log.v("LineupGrid", "Weight " + weight + " less than 1f");
							//we have a show that is shorter than the alloted time per column
							do {
								//increment the current show index and get the next show
								// if there is one..
								showIndex++;
								if (showIndex < networks.get(currentRow).Shows.size()) {
									currentShow = networks.get(currentRow).Shows.get(showIndex);
									//create another item time slot for the row
									weight = Float.valueOf(new DecimalFormat("#.#").format(Double.parseDouble(Float.toString(weight + Utility.CreateGridTimeSlot(getActivity(), currentShow, dataRow)))));
									//Log.v("LineupGrid", "New weight = " + weight);
									
									if (weight > cumlativeWeight) {
										cumlativeWeight++;
									}
								} else {
									//no more shows left.. break out of loop
									break;
								}
							} while (weight < cumlativeWeight);
						}
						
						//TODO: still got some bugs here!!
						showIndex++;
						columnIndex = columnIndex + (int)(weight / 1f);
					}
				}
			}
			
			dataTable.addView(dataRow, tblp);
		}
		
		Log.v("LineupGrid", "Completed Grid Render");
		view.requestLayout();
	}
	
	private void loadProviderList(List<Provider> providers) {
		mProviderDataAdapter = new ProviderDataListAdapter(getActivity(), 
				android.R.layout.simple_selectable_list_item, providers);
		((ListView)mDialogProviderListView).setAdapter(mProviderDataAdapter);
		((ListView)mDialogProviderListView).forceLayout();
	}
	
	private class LoadProviderData extends AsyncTask<String, Integer, List<Provider>> {
		ProgressDialog progress = new ProgressDialog(mCtx);
		Data data = new Data(mCtx);
		
		@Override
        public void onPreExecute() {
			progress.setCanceledOnTouchOutside(false);
			progress.setCancelable(false);
			progress.setMessage("Loading Providers ...");
			progress.show();
		}
		
		@Override
        public void onPostExecute(List<Provider> providers) {
			loadProviderList(providers);
			
			progress.dismiss();
		}
		
		@Override
		protected List<Provider> doInBackground(String... params) {
			return data.LoadProviders(params[0]);
		}
	}
	
	private class ProviderDataListAdapter extends ArrayAdapter<Provider>  {
		private List<Provider> mProviderItems;
		
		private LayoutInflater mInflater;
		
		public ProviderDataListAdapter(Context context, int textViewResourceId, List<Provider> providerList) {
			super(context, textViewResourceId, providerList);
			mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			mProviderItems = providerList;
			this.notifyDataSetChanged();
		}
		
		@Override
		public int getCount() {
			//handle instances where list is null, hence zero count
			int count = (mProviderItems == null) ? 0 : mProviderItems.size(); 
			return count;
		}
		
		@Override
		public Provider getItem(int position) {
			return mProviderItems.get(position);
		}
		
		@Override
		public long getItemId(int position) {
			return position;
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			
			if (v == null) {
				v = new TextView(mCtx);
			}
			
			TextView textView = (TextView)v;
			
			((TextView)v).setText(mProviderItems.get(position).Name);
			((TextView)v).setTag(R.id.zapid_tag_id, mProviderItems.get(position).ZapID);
			
			//redraw
			parent.refreshDrawableState();
			
			return v;
		}
	}
	
	private void presentProviderSelectionDialog() {
		//set up dialog
        final Dialog dialog = new Dialog(this.getActivity());
        dialog.setContentView(R.layout.provider_selection_dialog);
        dialog.setTitle("Select your Provider");
        dialog.setCancelable(true);
        
		mDialogProviderListView = ((ListView)dialog.findViewById(R.id.provider_list));
		
		mDialogProviderListView.setOnItemClickListener(new OnItemClickListener() {
		    public void onItemClick(AdapterView<?> adapter, View view, int position, long row) {
		    	mProviderZapId = view.getTag(R.id.zapid_tag_id).toString();
		    	dialog.dismiss();
		    	new LoadNetworkData().execute(mPostCode, mProviderZapId);
		    }
		});
		
        dialog.show();
        
        new LoadProviderData().execute(mPostCode);
	}
	
	private void buildHeaderRow(View container, int colCount) {
		//** create the header row **
		
		//grab instance of header row view and set the weightSum 
		TableRow headerRow = (TableRow) container.findViewById(R.id.header_row);
		headerRow.setWeightSum(colCount);
		
		//determine the starting time slot using the current time
		int startHour = Integer.parseInt(new SimpleDateFormat("HH").format(new Date()));
		double mins = Double.parseDouble(new SimpleDateFormat("mm").format(new Date()));
		
		//perform adjustments based on current minutes as I'm working in 30 minute slots 
		// 0-15 = (hr).0 | 16-30 = (hr).5 | 31-45 = (hr).5 | 46-59 = (hr+1).0  
		if (mins > 45) startHour++;
		
		mins = (mins <= 15) ? 0 : ((mins > 15) && (mins <= 30)) ? 0.5 
			: ((mins > 30) && (mins <= 45)) ? 0.5 : 0 ; 
		//this should now give us values like 10.5 (10:30a) or 17.0 (5:00p)  
		
		//loop through the colCount and create a column header for each slot
		for (int x=1;x<=colCount;x++) {
			// make a new vertical LinearLayout to hold the views
			LinearLayout colChild = new LinearLayout(getActivity());
			colChild.setOrientation(LinearLayout.VERTICAL);
			
			// new table row layout params, setting initial weight to 1f
			TableRow.LayoutParams tlp = new TableRow.LayoutParams(0, 
					TableRow.LayoutParams.WRAP_CONTENT, 1f);
			
			//create layout params for this view
			LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 
					LinearLayout.LayoutParams.WRAP_CONTENT);
			
			//generate a text view to sit within the layout, it's text will be the time slot
			TextView show = new TextView(getActivity());
			show.setText(((startHour <= 9) ? "0" + Integer.toString(startHour) : Integer.toString(startHour)) + ((mins == 0) ? ":00" : ":30"));
						
			show.setGravity(Gravity.CENTER);
			
			//add the text view to the layout
			colChild.addView(show, llp);
			
			if (x != 1) {
				colChild.setBackgroundResource(R.drawable.border);
				
				//increment the hour/min variables
				startHour = (mins == 0.5) ? startHour + 1 : startHour;
				if (startHour == 24) startHour = 0;
				mins = (mins == 0) ? 0.5 : 0;
			}
			
			//add the layout to the row with the defined layout params
			headerRow.addView(colChild, tlp);
		}
		
		((TextView)((LinearLayout)headerRow.getChildAt(0)).getChildAt(0)).setTextColor(Color.TRANSPARENT);
		headerRow.forceLayout();
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = container;
		
		super.onCreateView(inflater, container, savedInstanceState);
		
		view = inflater.inflate(R.layout.showtime_grid, container, false);
		
		return view;
	}
}
